<template>
  <!-- 图例 -->
  <div
    class="area_history_box"
    ref="area_history"
    v-show="showDialog"
    v-loading="searching"
    element-loading-text="查询中"
    element-loading-spinner="el-icon-loading"
    element-loading-background="#ffffffcc"
  >
    <h2 class="titleblue area_history_title" ref="area_history_title">
      <span>区域历史轨迹</span>
      <i class="close el-icon-close" @click="closeDialog" style="color: #fff; font-weight: normal;"></i>
    </h2>
    <div class="area_history_main">
      <div>
        <el-row>
          <el-col :span="24">
            <label>开始时间</label>
            <el-date-picker v-model="startTime" value-format='yyyy-MM-dd HH:mm:ss' type="datetime" placeholder="选择开始时间"
                            class="select-width-220">
            </el-date-picker>
          </el-col>
        </el-row>
        <el-row style="margin-top: 10px;">
          <el-col :span="24">
            <label>结束时间</label>
            <el-date-picker v-model="endTime" value-format='yyyy-MM-dd HH:mm:ss' type="datetime" placeholder="选择结束时间"
                            class="select-width-220">
            </el-date-picker>
          </el-col>
        </el-row>
        <el-row style="margin-top:10px;justify-content: flex-end;display:flex;padding-right:10px;align-items:center;">
          <el-button type="primary" size='mini' @click="pickArea">选择区域</el-button>
          <el-button type="primary" size='mini' @click="search">查询</el-button>
        </el-row>
      </div>
      <div>
        <el-row class="progress_row">
          <a @click="playOrPause" v-if="!playing"><i class="el-icon-video-play"></i></a>
          <a @click="playOrPause" v-else><i class="el-icon-video-pause"></i></a>
          <div style="flex:1;">
            <el-slider @change="progressChange" :show-tooltip="false" v-model="sliderValue" :min="sliderMin" :max="sliderMax"></el-slider>
          </div>
        </el-row>

        <el-row style="margin: 10px auto;">当前时刻：{{currentTime}}</el-row>

        <el-row class="speed_select">
          <span>播放速度：</span>
          <a @click="changeSpeed(0)" :class="speedIndex === 0 ? 'on' : ''">1x</a>
          <a @click="changeSpeed(1)" :class="speedIndex === 1 ? 'on' : ''">2x</a>
          <a @click="changeSpeed(2)" :class="speedIndex === 2 ? 'on' : ''">4x</a>
          <a @click="changeSpeed(3)" :class="speedIndex === 3 ? 'on' : ''">8x</a>
          <a @click="changeSpeed(4)" :class="speedIndex === 4 ? 'on' : ''">16x</a>
        </el-row>

        <el-row style="margin-top:10px;justify-content: flex-end;display:flex;padding-right:10px;align-items:center;">
          <el-button type="primary" size='mini' @click="toggleShipList">船只列表</el-button>
        </el-row>
      </div>
    </div>

    <div class="ret-ship-list" v-if="showShipList">
      <div class="list-row" v-for="item in selectedShipArray" :key="item.mmsi" @click="listClicked(item)">
        <span>{{item.mmsi}} {{item.name}}</span>
        <i class="el-icon-check" v-if="item.selected" />
      </div>
    </div>
  </div>
</template>

<script>
  import locationHisService from '@/services/LocationHisService'
  import mmsiTypecodeService from '@/services/MmsiTypecodeService'
  import * as shipService from '@/services/ShipService'
  import drag from '@/utils/drag'
  import config from '@/config'
  import moment from 'moment'
  const MAX_RECT_SQ = 300 * 1000 * 1000
  const KEYTIME_INTERVAL = 100
  export default {
    name: 'AreaHistory',
    props: ['map'],
    data () {
      return {
        showDialog: false,
        startTime: '',
        endTime: '',
        totalSeconds: 0,
        pickMode: false,
        dragging: false,
        startLatlng: null,
        rect: null,
        rectSq: null,
        speedIndex: 0,
        sliderValue: 0,
        playing: false,
        sliderMin: 1,
        sliderMax: 2,
        playingSeconds: 0,
        aisLayer: null,
        selectedShipArray: [],
        shipLabels: [],
        allLocDataArray: [],
        keyDataArray: [],
        mmsiColorMap: {},
        searching: false,
        currentTime: '',
        showShipList: true
      }
    },
    watch: {
      selectedShipArray: {
        deep: true,
        handler () {}
      },
      map: {
        deep: false,
        handler (newMap, oldMap) {
          if (!newMap.AreaHistoryLoaded) {
            // console.log('reload map.......')
            this.initControl()
          }
        }
      }
    },
    mounted () {
      drag(this.$refs.area_history_title, this.$refs.area_history)
      this.initControl()
    },
    methods: {
      initControl() {
        this.map.AreaHistoryLoaded = true
        let options = {
          position: 'topright',
          title: '区域历史轨迹',
          type: 'areahis',
          iconClass: 'el-icon-time'
        }
        L.control.iconcontrol(options).addTo(this.map)
        this.map.on('icon:areahis', () => {
          this.showDialog = !this.showDialog
          this.showDialog || this.setListener()
          this.showDialog || this.closeDialog()
          window.postMessage({
            type: 'hideAisLayer',
            value: this.showDialog
          })
          // this.$emit('visibleChanged', this.showDialog)
        })
      },
      setListener () {
        if (this.pickMode) {
          this.map.on('mousedown', this.mousedown)
          this.map.on('mousemove', this.mousemove)
          this.map.on('mouseup', this.mouseup)
          this.map.dragging.disable()
        } else {
          // console.log('off set........')
          this.map.off('mousedown', this.mousedown)
          this.map.off('mousemove', this.mousemove)
          this.map.off('mouseup', this.mouseup)
          this.map.dragging.enable()
        }
      },
      closeDialog () {
        this.showDialog = false
        this.pickMode = false
        this.stop()
        this.startTime = ''
        this.endTime = ''
        this.totalSeconds = 0
        this.pickMode = false
        this.draging = false
        this.startLatlng = null
        this.rect = null
        this.sliderValue = 0
        this.playing = false
        this.sliderMax = 2
        this.playingSeconds = 0
        this.aisLayer = null
        this.selectedShipArray = []
        this.shipLabels = []
        this.allLocDataArray = []
        this.keyDataArray = []
        this.mmsiColorMap = {}
        this.searching = false
        this.currentTime = ''
        this.showShipList = true
        if (this.rect) {
          this.rect.remove()
        }
        if (this.aisLayer) {
          this.aisLayer.removeFrom(this.map)
        }
        this.setListener()
        window.postMessage({
          type: 'hideAisLayer',
          value: this.showDialog
        })
        // this.$emit('visibleChanged', this.showDialog)
      },
      mousedown (e) {
        // console.log('mouse down event:::::', e)
        if (this.rect) {
          this.rect.remove()
          this.rect = null
        }

        this.startLatlng = e.latlng
        this.dragging = true
      },
      mousemove (e) {
        if (!this.dragging) {
          return
        }
        // drag rect
        let b = L.latLngBounds(this.startLatlng, e.latlng)
        if (!this.rect) {
          this.rect = L.rectangle(b, {color: '#fff', weight: 1}).addTo(this.map)
        } else {
          let bounds = this.rect.getBounds()
          let width = this.map.distance(bounds.getSouthWest(), bounds.getSouthEast())
          let height = this.map.distance(bounds.getSouthWest(), bounds.getNorthWest())
          // console.log('sq is ::::', width, height)
          this.rectSq = width * height
          if (this.rectSq < MAX_RECT_SQ) {
            this.rect.setBounds(b)
          }
        }
      },
      mouseup () {
        this.dragging = false
        this.pickMode = false
        this.setListener()
        // let bounds = this.rect.getBounds()
        // let width = this.map.distance(bounds.getSouthWest(), bounds.getSouthEast())
        // let height = this.map.distance(bounds.getSouthWest(), bounds.getNorthWest())
        // this.rectSq = width * height
        // console.log('sq is ::::', parseInt(this.rectSq / 1000000, 10))
      },
      changeSpeed (idx) {
        this.speedIndex = idx
      },
      playOrPause () {
        this.playing = !this.playing

        if (!this.aisLayer) {
          this.aisLayer = L.trackLayer()
          this.aisLayer.addTo(this.map)
        }

        if (this.playing && this.map.getZoom() < 11) {
          this.map.fitBounds(this.rect.getBounds())
        }

        if (this.playing) {
          this.playTimer = setInterval(this.drawFrame.bind(this), 1000)
        } else {
          clearInterval(this.playTimer)
        }
        // this.playingSeconds = 30
        // this.drawFrame()
      },
      stop () {
        this.playing = false
        clearInterval(this.playTimer)
      },
      progressChange (value) {
        this.playingSeconds = value
      },
      drawFrame () {
        let step = Math.pow(2, this.speedIndex)
        this.playingSeconds += step

        if (this.playingSeconds >= this.totalSeconds) {
          this.playingSeconds = this.totalSeconds
          this.stop()
        }
        this.sliderValue = this.playingSeconds
        this.currentTime = moment(this.startTime).add(this.playingSeconds, 's').format('YYYY-MM-DD hh:mm:ss')
        let keySecondsIndex = parseInt(this.playingSeconds / KEYTIME_INTERVAL, 10)
        if (keySecondsIndex < this.keyDataArray.length) {
          let ships = {...this.keyDataArray[keySecondsIndex].ships}
          for (let i = keySecondsIndex * KEYTIME_INTERVAL; i < this.playingSeconds; i++) {
            let ary = this.allLocDataArray[i] || []
            ary.forEach(loc => {
              ships[loc.terminalCode] = loc
            })
          }
          this.drawShips(ships)
        }
      },
      drawShips (ships) {
        // console.log('ships:::::::::', ships)
        this.aisLayer.clearLayers()
        Object.values(ships).forEach(ship => {
          ship.color = this.mmsiColorMap[ship.terminalCode]
          let marker = this.drawOneShip(ship)
          if (marker) {
            this.aisLayer.addTrack(marker)
          }
        })
      },
      drawOneShip (ship) {
        let flag = this.selectedShipArray.find(s => s.mmsi === ship.terminalCode).selected
        if (!flag) {
          return null
        }
        let myIcon = L.divIcon({
          className: '',
          html: '<div class="ship-label"><span>' + (ship.name || ship.terminalCode) + '</span></div>'
        });
        let latLng = L.latLng([ship.latitude, ship.longitude]);
        let lblMarker = L.marker(latLng, {icon: myIcon});
        this.shipLabels[ship.terminalCode] = lblMarker;

        // console.log('new add ship::::', ship.terminalCode);
        let marker = L.trackSymbol({lat: ship.latitude, lng: ship.longitude}, {
          trackId: ship.terminalCode,
          fill: true,
          fillColor: ship.color,
          fillOpacity: 1.0,
          stroke: true,
          color: '#000000',
          opacity: 1.0,
          weight: 1.0,
          speed: ship.speed,
          course: ship.course,
          heading: ship.trueHeading,
          minSilouetteZoom: 11
        }).bindTooltip(this.makeShipTooltip);
        marker.ship = ship
        marker.on({
          'mouseover': e => {
            // console.log(e.target);
            marker.openTooltip();
          },
          'mouseout': e => {
            marker.closeTooltip();
          },
          'click': e => {
            if (this.focusShipMarker) {
              this.focusShipMarker.blur();
            }
            marker.focus();
            if (this.focusShipMarker) {
              this.focusShipMarker.closeTooltip();
            }
            this.focusShipMarker = marker;
            setTimeout(() => {
              marker.openTooltip();
            }, 500);
            this.$emit('shipClicked', {
              mmsi: ship.terminalCode
            })
            // this.map.setView(marker.getLatLng());
            // if (this._shipOnClickCallback) {
            //   this._shipOnClickCallback(ship.terminalCode);
            // }
          }
        })

        return marker;
      },
      pickArea () {
        this.pickMode = true
        this.setListener()
      },
      toggleShipList () {
        this.showShipList = !this.showShipList
      },
      listClicked (item) {
        item.selected = !item.selected
        // console.log('item is::::', item)
      },
      search () {
        // this.map.eachLayer(layer => {
        //   console.log('layer::::', layer.name)
        // })
        // return;
        // this.startTime = '2019-10-01T02:00:00Z'
        // this.endTime = '2019-10-01T04:00:00Z'
        // let sw = {
        //   lat: 39,
        //   lng: 119
        // }
        // let ne = {
        //   lat: 39.5,
        //   lng: 119.5
        // }
        if (!this.rect) {
          return this.$alert('请先选择区域')
        }
        if (!this.startTime) {
          return this.$alert('请先指定开始时间')
        }
        if (!this.endTime) {
          return this.$alert('请先指定结束时间')
        }
        let m1 = new moment(this.startTime)
        let m2 = new moment(this.endTime)
        if (m1.unix() >= m2.unix()) {
          return this.$alert('开始时间应小于结束时间')
        }
        // console.log(m2.unix() - m1.unix())
        if (m2.unix() - m1.unix() > 7200) {
          return this.$alert('查询时间最长为2小时')
        }
        this.totalSeconds = m2.unix() - m1.unix()
        // console.log('total seconds::::', this.totalSeconds)
        this.sliderMax = this.totalSeconds
        this.sliderValue = 1
        let sw = this.rect.getBounds().getSouthWest()
        let ne = this.rect.getBounds().getNorthEast()
        this.searching = true

        locationHisService.getHistoryData(sw, ne, m1, m2).then(res => {
          let startSec = m1.unix()
          let gpsArray = []
          let mmsiMap = {}
          res.forEach(p => {
            mmsiMap[p.terminalCode] = p.terminalCode
            let t = moment(p.aisTime).unix() - startSec
            if (!gpsArray[t]) {
              gpsArray[t] = []
            }
            gpsArray[t].push(p)
          })
          this.allLocDataArray = gpsArray
          // 关键时间点船位数据（每100秒生成一个船位快照）
          this.keyDataArray = []
          this.keyDataArray.push({
            seconds: 0,
            ships: {}
          })
          let diff = m2.unix() - m1.unix()
          let keyData = {}
          let locMap = {}
          for (let i = 0; i < diff; i++) {
            let ary = gpsArray[i] || []
            ary.forEach(loc => {
              locMap[loc.terminalCode] = loc
            })
            if (i % KEYTIME_INTERVAL === 0 && i > 0) {
              keyData.seconds = i
              keyData.ships = {...locMap}
              this.keyDataArray.push(keyData)
              keyData = {}
              // locMap = {}
            }
          }
          // console.log('key data array::::::', this.keyDataArray)
          // 所有可选船舶的列表
          if (Object.keys(mmsiMap).length > 0) {
            let mmsis = Object.keys(mmsiMap).join(',')
            shipService.ps('mmsi=in=' + mmsis).then(res => {
              let obj = {}
              res.forEach(ship => {
                obj[ship.mmsi] = {
                  mmsi: ship.mmsi,
                  name: ship.enName || ship.mmsi,
                  selected: true
                }
              })
              Object.keys(mmsiMap).forEach(mmsi => {
                if (!obj[mmsi]) {
                  obj[mmsi] = {mmsi, name: '', selected: true}
                }
              })
              this.selectedShipArray = Object.values(obj)
              // console.log('res:::::', res, this.selectedShipArray)
              // console.log('get data:::::', res)
            })

            mmsiTypecodeService.search('mmsi=in=' + mmsis).then(res => {
              this.mmsiColorMap = {}
              Object.keys(mmsiMap).forEach(mmsi => {
                this.mmsiColorMap[mmsi] = config.SHIP_COLOR_DEFAULT
              })
              res.forEach(item => {
                let t = config.SHIP_COLOR_ARRAY.find(s => item.typeCode.startsWith(s.code))
                if (t) {
                  this.mmsiColorMap[item.mmsi] = t.color
                }
              })
              // console.log('result......', this.mmsiColorMap)
            })
          }
          this.searching = false
          // console.log('query result:', Object.keys(mmsiMap), gpsArray)
        }).catch(err => {
          this.searching = false
          this.$message.warning('查询轨迹出错，请稍候再试')
        })
      },
      makeShipTooltip (marker) {
        // debugger
// console.log(marker.getTrackId(), this.shipSet)
//         let ship = this.shipSet[marker.getTrackId()];
        let tm = moment(marker.ship.aisTime).format('YYYY-MM-DD HH:mm:ss');
        let ship = this.selectedShipArray.find(s => s.mmsi === marker.ship.terminalCode)
        // ship.shipInfo = ship.shipInfo || dataGenerator.getShipInfo(ship.terminalCode);
        // console.log(`course=${ship.course}, heading=${ship.heading}`, marker.getCourse(), marker.getHeading());
        return `<div class="ship-tt-container">${ship.name || ship.mmsi}<hr/><div>标识代码：${ship.mmsi}</div><div>船舶速度：${marker.ship.speed}节</div><div>最后时间：${tm}</div></div>`
      }
    }
  }
</script>

<style lang="scss" scoped>
  .area_history_box{
    width:560px;
    background: #fff;
    z-index: 999;
    position: absolute;
    right: 50px;
    top: 150px;
    overflow: hidden;
    box-shadow: 3px 3px 3px rgba(0, 0, 0, .3);
    font-size: 14px;

    .area_history_main {
      display: flex;
      flex-direction: row;
      padding: 10px;
    }

    .area_history_title{
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      font-size: 16px;
      color:#fff;
      line-height:32px;
      height:32px;
      background-color: #0062cd;
      padding-left:10px;
      padding-right:10px;
      .close{
        line-height: 32px;
        cursor: pointer;
      }
    }

    .area_history_main>div {
      flex: 1;
    }

    .el-radio-button__inner {
      padding: 5px 10px;
    }

    .speed_select {

      a {
        padding:3px 8px;
        font-size: 12px;
        border:solid 1px #666;
      }

      a.on {
        color:#fff;
        background-color:#0062cd;
      }
    }

    .progress_row {
      display: flex;
      flex-direction:row;
      align-items:center;
      padding-right:10px;

      a {
        margin-right:20px;
        font-size:26px;
        color:#0062cd;
      }
    }

    .ret-ship-list {
      display: flex;
      flex-direction:row;
      flex-wrap: wrap;
      max-height: 100px;
      overflow-y: auto;

      .list-row {
        width: 260px;
        border-bottom: solid 1px #ccc;
        padding: 8px 5px;
        margin-left:5px;
        position: relative;

        i {
          position:absolute;
          top:10px;
          right:5px;
          color:green;
        }
      }
    }
  }

</style>
